
#include "main.h"


#define gpio_CH1_TX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH1_TX_PORT		GPIOA
#define gpio_CH1_TX_PIN			GPIO_Pin_9
#define gpio_CH1_TX_AFTYPE		eAFCLK_APB2
#define gpio_CH1_TX_AFCLK		RCC_APB2Periph_USART1
#define gpio_CH1_TX_AFPINSRC	GPIO_PinSource9
#define gpio_CH1_TX_AF			GPIO_AF_USART1
#define gpio_CH1_RX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH1_RX_PORT		GPIOA
#define gpio_CH1_RX_PIN			GPIO_Pin_10
#define gpio_CH1_RX_AFTYPE		eAFCLK_APB2
#define gpio_CH1_RX_AFCLK		RCC_APB2Periph_USART1
#define gpio_CH1_RX_AFPINSRC	GPIO_PinSource10
#define gpio_CH1_RX_AF			GPIO_AF_USART1
#define uart_CH1_PORT			USART1
#define uart_CH1_IRQ			USART1_IRQn

#if		defined(BSP_DEVICE_TOUCH)

#define gpio_CH2_TX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH2_TX_PORT		GPIOA
#define gpio_CH2_TX_PIN			GPIO_Pin_2
#define gpio_CH2_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH2_TX_AFCLK		RCC_APB1Periph_USART2
#define gpio_CH2_TX_AFPINSRC	GPIO_PinSource2
#define gpio_CH2_TX_AF			GPIO_AF_USART2
#define gpio_CH2_RX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH2_RX_PORT		GPIOA
#define gpio_CH2_RX_PIN			GPIO_Pin_3
#define gpio_CH2_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH2_RX_AFCLK		RCC_APB1Periph_USART2
#define gpio_CH2_RX_AFPINSRC	GPIO_PinSource3
#define gpio_CH2_RX_AF			GPIO_AF_USART2
#define uart_CH2_PORT			USART2
#define uart_CH2_IRQ			USART2_IRQn

#define gpio_CH3_TX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_TX_PORT		GPIOB
#define gpio_CH3_TX_PIN			GPIO_Pin_10
#define gpio_CH3_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_TX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH3_TX_AF			GPIO_AF_USART3
#define gpio_CH3_RX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_RX_PORT		GPIOB
#define gpio_CH3_RX_PIN			GPIO_Pin_11
#define gpio_CH3_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_RX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH3_RX_AF			GPIO_AF_USART3
#define uart_CH3_PORT			USART3
#define uart_CH3_IRQ			USART3_IRQn

#elif	defined(BSP_DEVICE_CAMERA)

#define gpio_CH3_TX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_TX_PORT		GPIOB
#define gpio_CH3_TX_PIN			GPIO_Pin_10
#define gpio_CH3_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_TX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH3_TX_AF			GPIO_AF_USART3
#define gpio_CH3_RX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_RX_PORT		GPIOB
#define gpio_CH3_RX_PIN			GPIO_Pin_11
#define gpio_CH3_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_RX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH3_RX_AF			GPIO_AF_USART3
#define uart_CH3_PORT			USART3
#define uart_CH3_IRQ			USART3_IRQn

#define gpio_CH4_TX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_TX_PORT		GPIOC
#define gpio_CH4_TX_PIN			GPIO_Pin_10
#define gpio_CH4_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_TX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH4_TX_AF			GPIO_AF_UART4
#define gpio_CH4_RX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_RX_PORT		GPIOC
#define gpio_CH4_RX_PIN			GPIO_Pin_11
#define gpio_CH4_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_RX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH4_RX_AF			GPIO_AF_UART4
#define uart_CH4_PORT			UART4
#define uart_CH4_IRQ			UART4_IRQn

#endif	//BSP_DEVICE_xxx

#define	rx_BUF_MAXLEN			4096


static struct
{
	USART_TypeDef*	Port;

	u8				TxBuf[rx_BUF_MAXLEN];
	vu16			TxHead;
	vu16			TxTail;

	u8				RxBuf[rx_BUF_MAXLEN];
	vu16			RxHead;
	vu16			RxTail;

	u8				PktBuf[UART_PKT_MAX_LEN];
	u16				PktCnt;
	u16				PktLen;

#if		defined(BSP_DEVICE_TOUCH)
	u32				PingSecond;
#endif	//BSP_DEVICE_TOUCH

} _Uarts[eUART_MAX] = {
#if		defined(BSP_DEVICE_TOUCH)
	{uart_CH2_PORT,},
	{uart_CH3_PORT,},
#elif	defined(BSP_DEVICE_CAMERA)
	{uart_CH3_PORT,},
	{uart_CH4_PORT,},
#endif	//BSP_DEVICE_xxx
};


void Uart_Init(void)
{
	GPIO_INIT gis[] =
	{
		{gpio_CH1_TX_CLK, {gpio_CH1_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH1_TX_PORT,
			gpio_CH1_TX_AFTYPE, gpio_CH1_TX_AFCLK, gpio_CH1_TX_AFPINSRC, gpio_CH1_TX_AF},
		{gpio_CH1_RX_CLK, {gpio_CH1_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH1_RX_PORT,
			gpio_CH1_RX_AFTYPE, gpio_CH1_RX_AFCLK, gpio_CH1_RX_AFPINSRC, gpio_CH1_RX_AF},
#if		defined(BSP_DEVICE_TOUCH)
		{gpio_CH2_TX_CLK, {gpio_CH2_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH2_TX_PORT,
			gpio_CH2_TX_AFTYPE, gpio_CH2_TX_AFCLK, gpio_CH2_TX_AFPINSRC, gpio_CH2_TX_AF},
		{gpio_CH2_RX_CLK, {gpio_CH2_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH2_RX_PORT,
			gpio_CH2_RX_AFTYPE, gpio_CH2_RX_AFCLK, gpio_CH2_RX_AFPINSRC, gpio_CH2_RX_AF},
		{gpio_CH3_TX_CLK, {gpio_CH3_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_TX_PORT,
			gpio_CH3_TX_AFTYPE, gpio_CH3_TX_AFCLK, gpio_CH3_TX_AFPINSRC, gpio_CH3_TX_AF},
		{gpio_CH3_RX_CLK, {gpio_CH3_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_RX_PORT,
			gpio_CH3_RX_AFTYPE, gpio_CH3_RX_AFCLK, gpio_CH3_RX_AFPINSRC, gpio_CH3_RX_AF},
#elif	defined(BSP_DEVICE_CAMERA)
		{gpio_CH3_TX_CLK, {gpio_CH3_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_TX_PORT,
			gpio_CH3_TX_AFTYPE, gpio_CH3_TX_AFCLK, gpio_CH3_TX_AFPINSRC, gpio_CH3_TX_AF},
		{gpio_CH3_RX_CLK, {gpio_CH3_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_RX_PORT,
			gpio_CH3_RX_AFTYPE, gpio_CH3_RX_AFCLK, gpio_CH3_RX_AFPINSRC, gpio_CH3_RX_AF},
		{gpio_CH4_TX_CLK, {gpio_CH4_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_TX_PORT,
			gpio_CH4_TX_AFTYPE, gpio_CH4_TX_AFCLK, gpio_CH4_TX_AFPINSRC, gpio_CH4_TX_AF},
		{gpio_CH4_RX_CLK, {gpio_CH4_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_RX_PORT,
			gpio_CH4_RX_AFTYPE, gpio_CH4_RX_AFCLK, gpio_CH4_RX_AFPINSRC, gpio_CH4_RX_AF},
#endif	//BSP_DEVICE_xxx
	};
	UART_INIT uis[] =
	{	/* 115200, 256000, 1875000, 3750000 */
		#define _BAUDRATE	1875000
		{uart_CH1_PORT,
			{115200, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH1_IRQ, 0, 1, ENABLE}},
#if		defined(BSP_DEVICE_TOUCH)
		{uart_CH2_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH2_IRQ, 0, 0, ENABLE}},
		{uart_CH3_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH3_IRQ, 0, 0, ENABLE}},
#elif	defined(BSP_DEVICE_CAMERA)
		{uart_CH3_PORT,
			{1875000, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH3_IRQ, 0, 0, ENABLE}},
		{uart_CH4_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH4_IRQ, 0, 0, ENABLE}},
#endif	//BSP_DEVICE_xxx
	};

	Util_GpioInit(gis, _countof(gis));
	Util_UartInit(uis, _countof(uis));
}

int fputc(int ch, FILE *f)
{
	/*USART_SendData(uart_CH1_PORT, ch);
	while (USART_GetFlagStatus(uart_CH1_PORT, USART_FLAG_TXE) == RESET);*/
	uart_CH1_PORT->DR = (ch & (u16)0x01FF);
	while (0 == (uart_CH1_PORT->SR & USART_FLAG_TXE));

	return ch;
}
void USART1_IRQHandler(void)
{
	if (SET == USART_GetITStatus(uart_CH1_PORT, USART_IT_RXNE))
	{
		u8 rx = (u8)(uart_CH1_PORT->DR & 0xFF);
		fputc(rx, (FILE *)1);
	}

	/*if (SET == USART_GetITStatus(uart_CH1_PORT, USART_IT_TXE)){}*/
}

static void irqProcs(u8 uart)
{
	if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_IT_RXNE))
	{
		u8 rxData = _Uarts[uart].Port->DR;
		u16 uHead = _Uarts[uart].RxHead;

		_Uarts[uart].RxBuf[uHead++] = rxData;
		if (rx_BUF_MAXLEN == uHead)
			uHead = 0;
		_Uarts[uart].RxHead = uHead;
	}

	if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_IT_TXE))
	{
		u16 uTail = _Uarts[uart].TxTail;

		if (_Uarts[uart].TxHead != uTail)
		{
			_Uarts[uart].Port->DR = _Uarts[uart].TxBuf[uTail++];
			if (rx_BUF_MAXLEN == uTail)
				uTail = 0;
			_Uarts[uart].TxTail = uTail;
		}
		else
		{
			USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, DISABLE);
		}
	}
}
#if		defined(BSP_DEVICE_TOUCH)
void USART2_IRQHandler(void)
{
	irqProcs(eUART_CH2);
}
void USART3_IRQHandler(void)
{
	irqProcs(eUART_CH3);
}
#elif	defined(BSP_DEVICE_CAMERA)
void USART3_IRQHandler(void)
{
	irqProcs(eUART_CH3);
}
void UART4_IRQHandler(void)
{
	irqProcs(eUART_CH4);
}
#endif	//BSP_DEVICE_xxx


static void uartPkt_Parsing(u8 uart, u16 wPktLen, u8 *pPktData);


void Uart_PktProc(void)
{
	u16 wTail, wCount, i;

	for (u8 uart=eUART_MIN; uart<eUART_MAX; uart++)
	{
		wTail = _Uarts[uart].RxTail;

		wCount = (((_Uarts[uart].RxHead + rx_BUF_MAXLEN) - wTail) % rx_BUF_MAXLEN);
		for (i=0; i<wCount; i++)
		{
			_Uarts[uart].PktBuf[_Uarts[uart].PktCnt++] = _Uarts[uart].RxBuf[wTail++];
			if (rx_BUF_MAXLEN == wTail)
				wTail = 0;

			if (UART_PKT_POS_SOH1 == _Uarts[uart].PktCnt)
			{
				_Uarts[uart].PktLen = 0;
				if (UART_PKT_SOHS[UART_PKT_POS_SOH0] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH0])
					_Uarts[uart].PktCnt = 0;
			}
			else if (UART_PKT_POS_SOH2 == _Uarts[uart].PktCnt)
			{
				if (UART_PKT_SOHS[UART_PKT_POS_SOH1] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH1])
					_Uarts[uart].PktCnt = 0;
			}
			else if (UART_PKT_POS_SOH3 == _Uarts[uart].PktCnt)
			{
				if (UART_PKT_SOHS[UART_PKT_POS_SOH2] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH2])
					_Uarts[uart].PktCnt = 0;
			}
			else if (UART_PKT_POS_CMD == _Uarts[uart].PktCnt)
			{
				if (UART_PKT_SOHS[UART_PKT_POS_SOH3] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH3])
					_Uarts[uart].PktCnt = 0;
			}
			else if (UART_PKT_POS_DATA == _Uarts[uart].PktCnt)
			{
				u16 wDataLen = MAKEWORD(_Uarts[uart].PktBuf[UART_PKT_POS_DLEN0], _Uarts[uart].PktBuf[UART_PKT_POS_DLEN1]);
				_Uarts[uart].PktLen = wDataLen + UART_PKT_HEAD_LEN;
			}

			if (_Uarts[uart].PktCnt && (_Uarts[uart].PktLen == _Uarts[uart].PktCnt))
			{
				uartPkt_Parsing(uart, _Uarts[uart].PktLen, _Uarts[uart].PktBuf);
				_Uarts[uart].PktCnt = 0;

#if		defined(BSP_DEVICE_TOUCH)
				_Uarts[uart].PingSecond = g_vu32SysTickSecond + 5;
#endif	//BSP_DEVICE_TOUCH
			}
		}

		_Uarts[uart].RxTail = wTail;
	}

#if		defined(BSP_DEVICE_TOUCH)
	if (0 == (g_vu32SysTickSecond%3))	// 3, 6, 9, ...
	{
		static u32 _LastSecond = 0;
		if (_LastSecond != g_vu32SysTickSecond)
		{
			u8 errUart = 0;
			for (u8 uart=eUART_MIN; uart<eUART_MAX; uart++)
			{
				if (_Uarts[uart].PingSecond < g_vu32SysTickSecond)
				{
					errUart = uart + 1;
					break;
				}
			}

			if (errUart && g_TCD.bBeepAlert)
			{
				printf("EVT_CAMERA_PING : ERROR TIMEOUT %d\r\n", errUart);
				g_u32BuzzerDelay = g_vu32SysTickCount + (100 * 10);	// *[10msec]
				Led_Set(eLED_BUZZER, 1);
			}

			_LastSecond = g_vu32SysTickSecond;
		}
	}
#endif	//BSP_DEVICE_TOUCH
}

void Uart_PktCmd(u8 uart, u8 cmd, u8 dev, u16 len, u8 *data)
{
	u16 uHead, i;
	u8 head[UART_PKT_HEAD_LEN];

	uHead = _Uarts[uart].TxHead;

	memcpy(head, UART_PKT_SOHS, 4);
	head[UART_PKT_POS_CMD]   = cmd;
	head[UART_PKT_POS_DEV]   = dev;
	head[UART_PKT_POS_DLEN0] = LOBYTE(len);
	head[UART_PKT_POS_DLEN1] = HIBYTE(len);
	for (i=0; i<UART_PKT_HEAD_LEN; i++)
	{
		_Uarts[uart].TxBuf[uHead++] = head[i];
		if (rx_BUF_MAXLEN == uHead)
			uHead = 0;
	}

	for (i=0; i<len; i++)
	{
		_Uarts[uart].TxBuf[uHead++] = data[i];
		if (rx_BUF_MAXLEN == uHead)
			uHead = 0;
	}

	_Uarts[uart].TxHead = uHead;
	USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, ENABLE);
}

void Uart_PktRes(u8 uart, u8 req, u8 dev, u8 cmd, u16 len, u8 *data)
{
	u16 uHead, i;
	u8 head[UART_PKT_HEAD_LEN];

	uHead = _Uarts[uart].TxHead;

	memcpy(head, UART_PKT_SOHS, 4);
	head[UART_PKT_POS_CMD]   = req;
	head[UART_PKT_POS_DEV]   = dev;
	head[UART_PKT_POS_DLEN0] = LOBYTE(len) + 1;
	head[UART_PKT_POS_DLEN1] = HIBYTE(len);
	for (i=0; i<UART_PKT_HEAD_LEN; i++)
	{
		_Uarts[uart].TxBuf[uHead++] = head[i];
		if (rx_BUF_MAXLEN == uHead)
			uHead = 0;
	}

	_Uarts[uart].TxBuf[uHead++] = cmd;
	if (rx_BUF_MAXLEN == uHead)
		uHead = 0;

	for (i=0; i<len; i++)
	{
		_Uarts[uart].TxBuf[uHead++] = data[i];
		if (rx_BUF_MAXLEN == uHead)
			uHead = 0;
	}

	_Uarts[uart].TxHead = uHead;
	USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, ENABLE);
}
void Uart_PktEvt(u8 uart, u8 evt, u8 dev, u16 len, u8 *data)
{
	Uart_PktCmd(uart, evt, dev, len, data);
}

static void uartPkt_Parsing(u8 uart, u16 wPktLen, u8 *pPktData)
{
	u8 cmd, *pdev, *pdata, err = ERR_SUCCESS;
	u16 dlen;

	cmd   =  pPktData[UART_PKT_POS_CMD];
	pdev  = &pPktData[UART_PKT_POS_DEV];
	dlen  =  MAKEWORD(pPktData[UART_PKT_POS_DLEN0], pPktData[UART_PKT_POS_DLEN1]);
	pdata = &pPktData[UART_PKT_POS_DATA];

#if		defined(BSP_DEVICE_TOUCH)
#if		defined(BSP_APP)
	Led_Toggle(eLED_PORT1 + (*pdev - DEV_CAMERA1));

	switch (cmd)
	{
	case EVT_CAMERA_INIT:
	case EVT_IMAGE_SIDEVIEW:
	case EVT_IMAGE_DETECTION:
	case EVT_RADIAN_DATA:
		break;
	case EVT_LINEEQ_DATA:
		Touch_AddData(*pdev, dlen, pdata);
		return;
	case EVT_CAMERA_PING:
		//printf("EVT_CAMERA_PING(%d)\r\n", *pdev);
		if ((DEV_CAMERA1 + uart) != *pdev)
		{
			printf("EVT_CAMERA_PING : ERROR DEV (%d != %d)\r\n", *pdev, (DEV_CAMERA1 + uart));
			if (g_TCD.bBeepAlert)
			{
				g_u32BuzzerDelay = g_vu32SysTickCount + (50 * 10);	// *[10msec]
				Led_Set(eLED_BUZZER, 1);
			}
		}
		return;
	}

	Usb_PktCmdEvt(cmd, *pdev, dlen, pdata);
#endif	//BSP_APP
	(void)cmd;		// warning
	(void)*pdev;	// warning
	(void)*pdata;	// warning
	(void)err;		// warning
	(void)dlen;		// warning

#elif	defined(BSP_DEVICE_CAMERA)
	switch (*pdev)
	{
	case DEV_CAMERA1:
	case DEV_CAMERA2:
	case DEV_CAMERA3:
	case DEV_CAMERA4:
		if (g_u8MyAddr == *pdev)
			err = Pkt_CmdProc(uart, cmd, *pdev, &dlen, pdata);
		else
			err = ERR_UNKNOWN_DEVICE;
		break;

	default:
		err = ERR_UNKNOWN_DEVICE;
		break;
	}

	if (ERR_SUCCESS == err)
	{
		Uart_PktRes(uart, CMD_RESULT_SUCCESS, *pdev, cmd, dlen, pdata);
	}
	else
	{
		#if	DBG_MSG_UART
		printf("err(%d) : cmd(%02X) dev(%d) dlen(%02X)\r\n", err, cmd, *pdev, dlen);
		#endif	//DBG_MSG_UART
		Uart_PktRes(uart, CMD_RESULT_ERROR, *pdev, cmd, 1, (u8 *)&err);
	}
#endif	//BSP_DEVICE_xxx
}

